In multi-purpose computing devices, operating systems are typically, though not exclusively, used to manage memory of the computing device for use by one or more applications executing on the computing device. For example, if two applications access memory on the computing device, then the operating system may allocate portions of the memory for use by the two applications such that both can access memory without corrupting data stored by the other.
This management and arbitration may be necessary to alleviate problems that may arise if an application attempts to use memory being used by another. For example, if two applications both attempt to use the same portion of a memory in the same or overlapping time periods, then the second may overwrite the data of the first, and the first may be unable to execute properly or even crash. Errors such as these have a significant impact on the user experience, particularly if they occur frequently.
Operating systems typically include a memory manager to which an application may send requests to carry out memory management tasks, such that the memory manager can arbitrate between processes for use of memory resources. For example, if an application wishes to store data either temporarily or permanently, the application may request that the memory manager allocate some amount of memory to the application. Later, when the application no longer needs the memory, the application may inform the memory manager of that and request that the allocated memory be deallocated (or “freed”) such that it may be used by another application. When a second application sends to the memory manager a request for memory, the memory manager may consult its records to determine portions of the memory that are not currently allocated, and allocate those to the second application.
Some software applications that may execute processes interacting with an operating system, for example, may include bugs or other programming flaws related to performing memory operations, and the software applications may fail as a result of memory errors even when the memory manager executes the memory operations correctly. These memory errors may result from inconsistencies that may arise between memory operations. For example, as described above, a software application may request that a first amount of memory be allocated to the application, and then write a second amount of data to the memory that is larger than the first amount. The inconsistencies between operations—in this example, the inconsistency in size between the first amount and the second amount—may cause memory errors that lead to failures in the software application. These failures could include improper executions caused by the memory errors, or even catastrophic errors or “crashes” that halt execution of the application.
Because of the effects of these programming bugs, software tools have been developed to attempt to identify programming bugs that cause these memory errors. These tools may be used during developmental testing of software applications.
For example, different types of “debugging” tools exist that may be used to identify bugs during developmental testing of software applications. Some software development applications, such as Visual Studio available from the Microsoft Corporation of Redmond, Wash., have tools such as these built in. In Visual Studio, a developer may choose to enable Application Verifier functionality during testing that may include the Page Heap functionality. Page Heap may be used to detect some memory errors including buffer over- and under-runs by monitoring allocation and usage of memory for the application being tested. In Page Heap, an amount of reserved extra memory (termed a “non-accessible page”) is placed following an allocated portion of heap memory (the normal, “user allocation” page), and the Application Verifier functionality is enabled to detect when information has been written to the non-accessible page. In this way, the debugging tool may identify errors and report them to the developer.
Such debugging tools, however, may not be used during runtime of a software application. Other tools have been developed to collect crash information when a crash is caused by a memory error, the collected information when analyzed may be used to identify memory errors. Such attempts to resolve crashes experienced during runtime have traditionally been limited to detecting when such errors occur and reporting the conditions of the crash to a central aggregation point that may then inform the developer of the available information about the error. The developer can attempt to recreate or debug the error using this information, and then identify and resolve the bug. The Windows operating system available from the Microsoft Corporation offers such reporting functionality in its Windows Error Reporting (WER) system. In this system, when WER detects that an application has uncleanly exited—by, for example, crashing or otherwise exiting improperly—information regarding the state of the application, such as the contents of an instruction stack, may be bundled and reported to an aggregation server by WER. This information may also include a generic system error code identifying a class of error, but does not include information regarding the exact bug that caused the error.